﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Threading;
using System.Windows.Forms;
using System.Diagnostics;
using System.Text;

namespace TileMaker
{
    partial class MainWindow
    {
        static object _ActiveWorkersLock = new object();
        static int _CountOfActiveWorkers;

        void Tile(object state)
        {
            try
            {
                object[] State = state as object[];

                Bitmap Input = (Bitmap)State[0];
                Rectangle r = (Rectangle)State[1];
                string filename = (string)State[2];

                //DevIL.DevIL.SaveBitmap(filename, Crop(Input, r));
                Crop(Input, r).Save(filename);
            }
            finally
            {
                lock (_ActiveWorkersLock)
                {
                    --_CountOfActiveWorkers;
                    Monitor.PulseAll(_ActiveWorkersLock);
                }
            }
        }
        
        void Split(Bitmap Input, int tilelength, Rectangle snappedTile, string Body, TileCoordinates first)
        {
            if (!Miscallenous.IsPowerOfTwo((ulong)tilelength)) throw new ArgumentException("Tile Length must be power of two");

            Status.Text = "Thread Pool started. Booting up operations ...";

            sw.Restart();

            int cols = (int)Math.Truncate((float)snappedTile.Width / (float)tilelength);
            int rows = (int)Math.Truncate((float)snappedTile.Height / (float)tilelength);

            string ID = UniqueID.GetNewID();
            string filepath = System.IO.Path.Combine(System.Windows.Forms.Application.StartupPath, ID);
            Directory.CreateDirectory(filepath);

            List<string> BaseAdd = new List<string>();

            for (int r = 0; r < rows; r++)
            {
                for (int c = 0; c < cols; c++)
                {
                    string name = String.Format(/*"{0}_{1}_{2}{3:0000}_{4}{5:0000}.dds"*/"{0}_{1}_{2}{3:0000}_{4}{5:0000}.bmp",
                                                                                        Body, first.Level,
                                                                                        (first.Longitude+c)<=0?"W":"E", first.Longitude+c,
                                                                                        (first.Latitude+r)<=0?"S":"E", first.Latitude+r);
                    BaseAdd.Add(String.Format("{0} {1} {2} 1", first.Level, first.Longitude + c, first.Latitude + r));

                    string fName = System.IO.Path.Combine(filepath, name);

                    Rectangle rect = new Rectangle(snappedTile.Left + c * tilelength,
                                                snappedTile.Top + r * tilelength,
                                                tilelength,
                                                tilelength);
                    lock (_ActiveWorkersLock)
                        ++_CountOfActiveWorkers;
                    System.Threading.ThreadPool.QueueUserWorkItem(Tile, new object[] { Input.Clone(), rect, fName });
                    Status.Text = String.Format("{3:00} thread{4} running. | Elapsed {0:00}:{1:00}.{2:000}", Math.Truncate(sw.Elapsed.TotalMinutes), sw.Elapsed.Seconds, sw.Elapsed.Milliseconds,
                                                                                                                                _CountOfActiveWorkers, _CountOfActiveWorkers == 1 ? "" : "s");
                    Application.DoEvents();
                }
            }

            lock (_ActiveWorkersLock)
            {
                while (_CountOfActiveWorkers > 0)
                {
                    Status.Text = String.Format("{3:00} thread{4} running. | Elapsed {0:00}:{1:00}.{2:000}", Math.Truncate(sw.Elapsed.TotalMinutes), sw.Elapsed.Seconds, sw.Elapsed.Milliseconds,
                                                                                                                                _CountOfActiveWorkers, _CountOfActiveWorkers == 1 ? "" : "s");
                    Application.DoEvents();

                    Monitor.Wait(_ActiveWorkersLock);
                }
            }

            sw.Stop();
            Status.Text = "Image tiling finished. Takes " + Miscallenous.GetDirectorySize(filepath) / (1024 * 1024) + " Mb. | " + String.Format("Elapsed {0:00}:{1:00}:{2:000}", Math.Truncate(sw.Elapsed.TotalMinutes), sw.Elapsed.Seconds, sw.Elapsed.Milliseconds);
            Process.Start(filepath);

            BaseAddTiles win = new BaseAddTiles();
            List<string> Lines = new List<string>();
            Lines.Add("BEGIN_SURFTILELIST");
            foreach (string line in BaseAdd)
                Lines.Add(line);
            Lines.Add("END_SURFTILELIST");

            win.textBox1.Lines = Lines.ToArray();
            win.Show();
        }
    }
}
